package com.hulk.dryad.manage.framework.limiter.config;


import com.hulk.dryad.manage.framework.limiter.aop.LimiterAspect;
import com.hulk.dryad.manage.framework.limiter.expression.LimiterInfoResolver;
import com.hulk.dryad.manage.framework.limiter.expression.LimiterKeyExpressionResolver;
import com.hulk.dryad.manage.framework.limiter.filter.LimiterIpFilter;
import com.hulk.dryad.manage.framework.limiter.strategy.LimiterStrategy;
import com.hulk.dryad.manage.framework.limiter.strategy.RedisLimiterStrategy;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.scripting.support.ResourceScriptSource;

import java.util.List;

/**
 * 限流
 *
 * @author hulk
 */
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class LimiterAutoConfiguration {



	@Bean
	@ConditionalOnMissingBean(name = "limitStringRedisTemplate")
	public StringRedisTemplate limitStringRedisTemplate(
			RedisConnectionFactory redisConnectionFactory) {
		return new StringRedisTemplate(redisConnectionFactory);
	}

	@Bean
   @SuppressWarnings("unchecked")
   public RedisScript redisRequestRateLimiterScript() {
      DefaultRedisScript redisScript = new DefaultRedisScript<>();
      redisScript.setScriptSource(new ResourceScriptSource(
              new ClassPathResource("META-INF/scripts/request_rate_limiter.lua")));
      redisScript.setResultType(List.class);
      return redisScript;
   }
   @Bean
   public RedisLimiterStrategy redisLimiterStrategy (RedisScript redisRequestRateLimiterScript, StringRedisTemplate limitStringRedisTemplate){
      return new RedisLimiterStrategy(redisRequestRateLimiterScript,limitStringRedisTemplate);
   }
	@Bean
	public LimiterKeyExpressionResolver limiterKeyExpressionResolver (){
		return  new LimiterKeyExpressionResolver();
	}
	@Bean
	public LimiterInfoResolver limiterInfoProvider (LimiterKeyExpressionResolver limiterKeyExpressionResolver){
		return  new LimiterInfoResolver(limiterKeyExpressionResolver);
	}
   @Bean
   public LimiterAspect limiterAspect (LimiterInfoResolver limiterInfoResolver, RedisLimiterStrategy redisLimiterStrategy){
   	    return  new LimiterAspect(limiterInfoResolver,redisLimiterStrategy);
   }
   @Bean
   public LimiterIpFilter limiterIpFilter(LimiterStrategy redisLimiterStrategy){
		return new LimiterIpFilter(redisLimiterStrategy);
	}

}
